package com.glsc.ngateway.platform.service.itflow.flowstrategy.equipmentApply;

import com.alibaba.excel.util.CollectionUtils;
import com.glsc.ngateway.common.api.flowable.dto.task.doTaskParam.AbstractFlowSearchParamDto;
import com.glsc.ngateway.common.api.flowable.dto.task.formData.equipment.EquipmentApplyTaskFormDataDto;
import com.glsc.ngateway.common.api.flowable.dto.task.formData.equipment.domainDto.FlowFormEquipmentApplyDto;
import com.glsc.ngateway.common.api.platform.dto.user.PlatformUserDto;
import com.glsc.ngateway.common.base.converter.platform.FlowFormEquipmentApplyCloudDeviceDetailConverter;
import com.glsc.ngateway.common.base.converter.platform.FlowFormEquipmentApplyConverter;
import com.glsc.ngateway.common.base.converter.platform.FlowFormEquipmentApplyVirtualDeviceDetailConverter;
import com.glsc.ngateway.common.base.domain.mysql.gateway.platform.flow.FlowFormEquipmentApply;
import com.glsc.ngateway.common.base.enums.itflow.ITFlowEnum;
import com.glsc.ngateway.common.base.enums.itflow.ITFlowTaskEnum;
import com.glsc.ngateway.common.base.enums.itflow.ITFlowTaskParamEnum;
import com.glsc.ngateway.common.base.enums.itflow.ITFlowTaskRoleEnum;
import com.glsc.ngateway.common.base.exception.PlatformException;
import com.glsc.ngateway.common.base.repo.mysql.gateway.platform.AppendixRepo;
import com.glsc.ngateway.common.base.repo.mysql.gateway.platform.FlowFormEquipmentApplyCloudDeviceRepo;
import com.glsc.ngateway.common.base.repo.mysql.gateway.platform.FlowFormEquipmentApplyRepo;
import com.glsc.ngateway.common.base.repo.mysql.gateway.platform.FlowFormEquipmentApplyVirtualDeviceRepo;
import com.glsc.ngateway.platform.service.FlowCommonService;
import com.glsc.ngateway.platform.service.RoleService;
import com.glsc.ngateway.platform.service.UserService;
import com.glsc.ngateway.platform.service.itflow.flowstrategy.AbstractItFlowStrategy;
import com.glsc.ngateway.platform.service.itflow.flowstrategy.equipmentApply.taskPostHandler.IEquipmentApplyTaskPostHandlerAudit;
import lombok.Getter;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.persistence.criteria.Predicate;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 设备申领流程策略类
 *
 * @author xuchang
 */
@Getter
@Component
public class EquipmentApplyFlowStrategy extends AbstractItFlowStrategy<FlowFormEquipmentApplyDto, EquipmentApplyTaskFormDataDto> {

    Logger logger = LoggerFactory.getLogger(EquipmentApplyFlowStrategy.class);

    @Resource
    private FlowFormEquipmentApplyRepo equipmentApplyRepo;

    @Resource
    private FlowFormEquipmentApplyCloudDeviceRepo equipmentApplyCloudServerRepo;

    @Resource
    private FlowFormEquipmentApplyVirtualDeviceRepo equipmentApplyVirtualDeviceRepo;

    @Resource
    private RoleService roleService;

    @Resource
    private UserService userService;

    private Map<String, IEquipmentApplyTaskPostHandlerAudit> taskPostHandlerMap;

    @Autowired
    public void setTaskPostHandlerMap(List<IEquipmentApplyTaskPostHandlerAudit> taskPostHandlerList) {
        this.taskPostHandlerMap = taskPostHandlerList.stream()
                .collect(Collectors.toMap(IEquipmentApplyTaskPostHandlerAudit::getTaskDefinitionKey, handler -> handler));
    }

    @Resource
    private FlowCommonService flowCommonService;

    @Resource
    private AppendixRepo appendixRepo;

    @Override
    public ITFlowEnum getFlowEnum() {
        return ITFlowEnum.EQUIPMENT_APPLY;
    }

    @Override
    protected Map<String, List<String>> initDefaultTaskUserGroup(PlatformUserDto creator) throws PlatformException {
        //流程节点，发起时动态指定节点处理人
        Map<String, List<String>> taskAssignee = new HashMap<>();
        //1、发起人
        taskAssignee.put(ITFlowTaskParamEnum.APPLY_FLOW_BEGIN_TASK_ASSIGNMENTS.getName(), Arrays.asList(creator.getUsername()));
        //2、直属ld+一级部门负责人
        List<String> superList = userService.getDirectLeaderAndPrimaryDepartmentLeader(creator).getAllLeaders();
        taskAssignee.put(ITFlowTaskParamEnum.APPLY_FLOW_DEPARTMENT_SUPER_TASK_ASSIGNMENTS.getName(), superList);
        //3、国联证券_设备管理员
        List<String> deviceAdminList = roleService.getUsersByRole(ITFlowTaskRoleEnum.ROLE_DEVICE_ADMIN.getRoleName());
        if (CollectionUtils.isEmpty(deviceAdminList)) {
            throw PlatformException.error("未找到设备管理员", false, false);
        }
        taskAssignee.put(ITFlowTaskParamEnum.APPLY_FLOW_DEVICE_ADMIN_TASK_ASSIGNMENTS.getName(), deviceAdminList);
        //4、网络安全部门负责人审核
        List<String> frameworkHeadList = roleService.getUsersByRole(ITFlowTaskRoleEnum.ROLE_FRAMEWORK_HEAD.getRoleName());
        if (CollectionUtils.isEmpty(frameworkHeadList)) {
            throw PlatformException.error("未找到信息技术总部基础架构部负责人", false, false);
        }
        taskAssignee.put(ITFlowTaskParamEnum.APPLY_FLOW_NETWORK_SECURITY_TASK_ASSIGNMENTS.getName(), frameworkHeadList);
        //5、设备管理员和病毒管理岗
        if (!CollectionUtils.isEmpty(deviceAdminList)) {
            taskAssignee.put(ITFlowTaskParamEnum.APPLY_FLOW_DEVICE_ADMIN_ASSIGNMENT_TASK_ASSIGNMENTS.getName(), deviceAdminList);
        }
        List<String> virusManagerList = roleService.getUsersByRole(ITFlowTaskRoleEnum.ROLE_VIRUS_MANAGER.getRoleName());
        if (!CollectionUtils.isEmpty(virusManagerList)) {
            taskAssignee.put(ITFlowTaskParamEnum.APPLY_VIRUS_MANAGE_TASK_ASSIGNMENTS.getName(), virusManagerList);
        }

        return taskAssignee;
    }

    @Override
    protected Map initDefaultTaskConditionalVar(Map<String, String> taskAssignee, PlatformUserDto createUser) {
        return Collections.EMPTY_MAP;
    }

    @Override
    public EquipmentApplyTaskFormDataDto saveOrUpdateForm(EquipmentApplyTaskFormDataDto flowableForm) {
        if (StringUtils.isNotBlank(flowableForm.getProcessId())) {
            flowableForm.getFormMainData().setProcessId(flowableForm.getProcessId());
        }
        FlowFormEquipmentApply oldData = equipmentApplyRepo.findByProcessId(flowableForm.getFormMainData().getProcessId());
        if (Objects.nonNull(oldData)) {
            flowableForm.getFormMainData().setId(oldData.getId());
        }
        FlowFormEquipmentApply equipmentApply = equipmentApplyRepo.save(Objects.requireNonNull(FlowFormEquipmentApplyConverter.dto2Do(flowableForm.getFormMainData())));
        Long equipmentApplyId = equipmentApply.getId();
        if (!CollectionUtils.isEmpty(flowableForm.getFormCloudDeviceDataList())) {
            FlowFormEquipmentApplyCloudDeviceDetailConverter.dto2Do(flowableForm.getFormCloudDeviceDataList())
                    .forEach(cloud -> {
                        cloud.setEquipmentApplyId(equipmentApplyId);
                        equipmentApplyCloudServerRepo.save(cloud);
                    });
        }
        if (!CollectionUtils.isEmpty(flowableForm.getFormVirtualDeviceDataList())) {
            FlowFormEquipmentApplyVirtualDeviceDetailConverter.dto2Do(flowableForm.getFormVirtualDeviceDataList())
                    .forEach(virtual -> {
                        virtual.setEquipmentApplyId(equipmentApplyId);
                        equipmentApplyVirtualDeviceRepo.save(virtual);
                    });
        }
        return flowableForm;
    }

    @Override
    public EquipmentApplyTaskFormDataDto findFormByProcessId(String processId) {
        //主表信息
        EquipmentApplyTaskFormDataDto formDataDto = new EquipmentApplyTaskFormDataDto();
        FlowFormEquipmentApply applyData = equipmentApplyRepo.findByProcessId(processId);
        boolean nullFlag = Objects.isNull(applyData);
        formDataDto.setFormMainData(nullFlag ? new FlowFormEquipmentApplyDto() : FlowFormEquipmentApplyConverter.do2Dto(applyData));
        //虚拟机信息
        formDataDto.setFormVirtualDeviceDataList(nullFlag ? Collections.emptyList() : FlowFormEquipmentApplyVirtualDeviceDetailConverter.do2Dto(equipmentApplyVirtualDeviceRepo.findByEquipmentApplyId(applyData.getId())));
        //云平台信息
        formDataDto.setFormCloudDeviceDataList(nullFlag ? Collections.emptyList() : FlowFormEquipmentApplyCloudDeviceDetailConverter.do2Dto(equipmentApplyCloudServerRepo.findByEquipmentApplyId(applyData.getId())));

        return formDataDto;
    }

    @Override
    public List<String> pageProcessId(AbstractFlowSearchParamDto param, Pageable pageable) {
        return equipmentApplyRepo.findAll(
                        (Specification<FlowFormEquipmentApply>) (root, query, builder) -> {
                            List<Predicate> predicateList = new ArrayList<>();
                            if (!io.jsonwebtoken.lang.Collections.isEmpty(param.getAdminList())) {
                                predicateList.add(builder.in(root.get("flowCreateOperatorName")).value(param.getAdminList()));
                            }
                            if (StringUtils.isNotBlank(param.getTitle())) {
                                predicateList.add(builder.equal(root.get("flowTitle"), param.getTitle()));
                            }
                            if (Objects.nonNull(param.getBeginDateLocalDate())) {
                                predicateList.add(builder.greaterThanOrEqualTo(root.get("flowApplyTime"), param.getBeginDateLocalDate()));
                            }
                            if (Objects.nonNull(param.getEndDateLocalDate())) {
                                predicateList.add(builder.lessThanOrEqualTo(root.get("flowApplyTime"), param.getEndDateLocalDate()));
                            }
                            if (Objects.nonNull(param.getHasProcessEnd())) {
                                predicateList.add(builder.equal(root.get("isClose"), param.getHasProcessEnd()));
                            }
                            return builder.and(predicateList.toArray(new Predicate[0]));
                        }, pageable)
                .getContent()
                .stream()
                .map(FlowFormEquipmentApply::getProcessId)
                .collect(Collectors.toList());
    }

    @Override
    protected Map<String, IEquipmentApplyTaskPostHandlerAudit> getTaskPassMap() {
        return taskPostHandlerMap;
    }

    @Override
    protected Map<String, IEquipmentApplyTaskPostHandlerAudit> getTaskRejectMap() {
        return taskPostHandlerMap;
    }
}
